
#include <Instruction.h>
#include <iostream>
#include <cstring>
#include <Directory.h>
#include <File.h>
#include <System.h>
#include <stdlib.h>
#include <fstream>
#include <iomanip>


bool __can(string name)        //名字是否合适
{
	const char* ch = name.c_str();
	if(strlen(ch) > 251 || name.size() == 0)
	{
		return false;
	}
	
	if(name[0] == ' ')
	{
		return false;
	}
	
	return true;
}

//初始化默认的指令出错信息
string Instruction::instrErrorMsg = string("can not find instruction.\n");
string Instruction::nameIllegal = string("The name can not be empty and the size of it can not be [1, 251]\n");



Instruction::Instruction()
{
	
}



string Instruction::execute(string cmd)
{
	//分割参数
	vector<string> vec = split(cmd, " ");
	
	try
	{
		if(vec.size() < 1)
		{
			return	instrErrorMsg;
		}else
		{
			//获得第一个参数-即命令名
			string cmdName = vec.at(0);
			//根据不同的命令名选择不同的函数执行
			if(cmdName == "ls")
			{
				return ls(vec);
			}else if(cmdName == "cd")
			{
				return cd(vec);
			}else if(cmdName == "open")
			{
				return open(vec);
			}else if(cmdName == "mkdir")
			{
				return mkdir(vec);
			}else if(cmdName == "rmdir")
			{
				return rmdir(vec);
			}else if(cmdName == "touch")
			{
				return touch(vec);
			}else if(cmdName == "rm")
			{
				return rm(vec);
			}else if(cmdName == "create")
			{
				return create(vec);
			}else if(cmdName == "import")
			{
				return _import(vec);
			}else if(cmdName == "export")
			{
				return _export(vec);
			}else if(cmdName == "pwd")
			{
				return pwd(vec);
			}else if(cmdName == "cat")
			{
				return cat(vec);
			}else if(cmdName == "df")
			{
				return df(vec);
			}else
			{
				return instrErrorMsg;
			}
			
		}
	}catch(string s)
	{
		return s;
	}
	
	return "";
}

//分割字符串
vector<string> Instruction::split(string str, string pattern)
{
    string::size_type pos;
    vector<string> result;

    str += pattern;//扩展字符串以方便操作
    int size = str.size();

    for (int i = 0; i<size; i++) {
        pos = str.find(pattern, i);
        if (pos<size) {
            std::string s = str.substr(i, pos - i);
            result.push_back(s);
            i = pos + pattern.size() - 1;
        }
    }
    return result;
}

//检查是否已经打开虚拟磁盘
void Instruction::checkEmpty()
{
	if(path.isEmpty())
	{
		throw string("There is no disk that has been opened. May be you want to try \"open diskname\".\n");
	}
}

//得到当前目录
string Instruction::getCurrentDirName()
{
	if(path.isEmpty())
	{
		return "";
	}else
	{
		return  ((Directory*)(path.top()))->getName();
	}
}

/*********************指令实现区****************************/


string Instruction::ls(vector<string> args)
{
	checkEmpty();
	Directory* top = (Directory*)(path.top());
	bool canDel = false;                           //是否可以把top删除
	if(args.size() == 1 || args.at(1) == ".")      //ls 当前目录
	{
		//TODO：什么也不做
	}else if(args.at(1) == "..")                   //ls 上级目录
	{
		for(Node* i = path.head->next; i->next != 0; i = i->next)
		{
			Directory* tempDir = (Directory*)(i->next->addr);
			if(tempDir == top)                     //找到目录栈项的上一个
			{
				top = (Directory*)(i->addr);
				break;
			}
		}
		//TODO：如果已经到项级目录，则变成列举当前目录
	}else if(args.at(1) == "/")                     //ls 根目录
	{
		top = (Directory*)(path.head->next->addr);
	}else if(args.size() == 2)
	{
		Directory* dir = top->getDir(args.at(1));
		if(dir == 0)
		{
			return "dirname '" + args.at(1) + "' is not exists\n";
		}else
		{
			top = dir;
			canDel = true;                           //因为dir是new出来的，所以要手动删除
		}
	}else
	{
		return "ls format error: see \"ls [.|..|/|subdir]\"\n";
	}
	
	//ls的功能实现
	vector<Directory*> dirs = top->getDirs();
	vector<File*> files = top->getFiles();
	ostringstream oss;
	oss << "[type]\t[size]\t[   create time   ]\t[   update time   ]\t[state]\t[name]\n";
	for(int i = 0; i < dirs.size(); i++)
	{
		Directory* dir = dirs.at(i);
		oss << "<DIR>" <<  "\t";
		oss << dir->size() << "\t";
		oss << setw(19) << dir->getCreateTime().toString() << "\t";
		oss << setw(19) << dir->getUpdateTime().toString() << "\t";
		oss << dir->getState() << "\t";
		oss << dir->getName() << endl;
		delete dir;
	}
	for(int i = 0; i < files.size(); i++)
	{
		File* file = files.at(i);
		oss << "<FILE>" << "\t";
		oss << file->size() << "\t";
		oss << setw(19) << file->getCreateTime().toString() << "\t";
		oss << setw(19) << file->getUpdateTime().toString() << "\t";
		oss << file->getState() << "\t";
		oss << file->getName() << endl;
		delete file;
	}
	if(canDel) delete top;
	return oss.str();
}

string Instruction::cd(vector<string> args)
{
	checkEmpty();
	if(args.size() == 1 || args.at(1) == ".")      //cd 当前目录
	{
		//TODO：什么也不做
	}else if(args.at(1) == "..")                   //cd 上级目录
	{
		if(path.size() > 1)
		{
			Directory* dir = (Directory* )(path.pop());
			delete dir;
		}else
		{
			return "Had reached to root.\n";
		}
	}else if(args.at(1) == "/")                    //cd 根目录
	{
		while(path.size() > 1)
		{
			Directory* dir = (Directory* )(path.pop());
			delete dir;
		}
		return "";
	}else                                          //cd 下级目录
	{
		Directory* top = (Directory*)(path.top());
		Directory* next = top->getDir(args.at(1));
		if(next != 0)
		{
			path.push((void*)next);
			
		}else
		{
			return "can not find dir '" + args.at(1) +"'\n";
		}
	}
	return "";
}


string Instruction::mkdir(vector<string> args)
{
	checkEmpty();
	Directory* top = (Directory*)(path.top());
	
	//检查参数长度
	if(args.size() < 2)
	{
		return "mkdir format error: see \"mkdir dirname\".\n";
	}
	
	//如果已经存在则不创建
	if(top->has(args.at(1)))
	{
		return "The name '" +args.at(1) + "' has exists\n";
	}
	
	//文件名是否合法
	if(!__can(args.at(1)))
	{
		return nameIllegal;
	}
	
	//创建
	bool result = top->createDir(args.at(1));
	if(result)
	{
		return "succeed\n";	
	}else
	{
		return "fail. Maybe the disk is full.\n";	
	}

}


string Instruction::rmdir(vector<string> args)
{
	checkEmpty();
	Directory* top = (Directory*)(path.top());
	
	//检查参数长度
	if(args.size() < 2)
	{
		return "rmdir format error: see \"rmdir dirname\".\n";
	}
	
	//删除
	if(top->removeDir(args.at(1)))
	{
		return "succeed\n";	
	}
	
	return "fail. Maybe the dirname is not correct\n";
}

string Instruction::touch(vector<string> args)
{
	checkEmpty();
	Directory* top = (Directory*)(path.top());
	
	////检查参数长度
	if(args.size() < 2)
	{
		return "touch format error: see \"touch filename\".\n";
	}
	
	//如果已经存在则不创建
	if(top->has(args.at(1)))
	{
		return "The name '" +args.at(1) + "' has exists\n";
	}
	
	//文件名是否合法
	if(!__can(args.at(1)))
	{
		return nameIllegal;
	}
	
	//创建
	bool result = top->createAFile(args.at(1));
	if(result)
	{
		return "succeed\n";	
	}else
	{
		return "fail. Maybe the disk is full.\n";	
	}
}


string Instruction::rm(vector<string> args)
{
	checkEmpty();
	Directory* top = (Directory*)(path.top());
	
	//检察参数长度
	if(args.size() < 2)
	{
		return "rm format error: see \"rm filename\".\n";
	}
	
	//删除
	if(top->removeAFile(args.at(1)))
	{
		return "succeed\n";	
	}
	
	return "fail. Maybe the filename is not correct\n";
}


string Instruction::open(vector<string> args)
{
	//如果已经打开
	if(!path.isEmpty())
	{
		return "A disk has already been opened. please exit and try again.\n";
	}
	
	//检察参数长度
	if(args.size() < 2)
	{
		return "open format error: see \"open diskname\".\n";
	}
	
	Directory* root = Directory::getRoot(args.at(1));
		
	//如果打开成功
	if(root == 0)
	{
		return "Has an error occured: during open an disk. Maybe the disk is not exists\n";
	}
	this->disk = args.at(1);
	path.push(root);
	return "open succeed\n";
}




string Instruction::create(vector<string> args)
{
	//参数长度检察
	if(args.size() < 3)
	{
		return "create format error: see \"create diskname size\".\n";
	}
	
	//判断文件是否存在
	ifstream file;
	file.open(args.at(1) + ".disk", ios::binary | ios::in);
	if(!file.fail())
	{
		return "The disk-file has been on physical disk\n";
	}
	file.close();
	
	//判断大小是否合法
	int size = atoi(args.at(2).c_str());
	if(size < 1 || size > 2 * 1024)
	{
		return "The size is illegal, which should be greater than 1 and less than 2 * 1024, but is";
	}
	
	//如果创始成功
	if(createDisk(args.at(1), size))
	{
		return "succeed\n";
	}else
	{
		return "fail. Maybe the env has no permissions to create a file\n";
	}
}

string Instruction::_import(vector<string> args)
{
	//环境检测
	checkEmpty();
	
	//参数检测
	if(args.size() < 3)
	{
		return "import format error: see\"import from to\"\n";
	}
	
	Directory* top = (Directory*)(path.top());
	
	//重名检测
	if(top->has(args.at(2)))
	{
		return "the filename '" + args.at(2) +"' has already exists";
	}
	
	//名字规范检测
	if(!__can(args.at(2)))
	{
		return nameIllegal;
	}
	
	//加载文件
	if(top->importFile(args.at(1), args.at(2)))
	{
		return "succeed\n";
	}
	
	return "unexpected error occured!\n";
}
	

	
string Instruction::_export(vector<string> args)
{
	//环境检测
	checkEmpty();
	
	//参数检测
	if(args.size() < 3)
	{
		return "export format error: see\"export from to\"\n";
	}
	
	Directory* top = (Directory*)(path.top());
	
	//加载文件
	if(top->exportFile(args.at(1), args.at(2)))
	{
		return "succeed\n";
	}
	
	return "unexpected error occured!\n";
}


string Instruction::pwd(vector<string> args)
{
	//环境检测
	checkEmpty();
	
	//循环构造字符串
	stringstream ss;
	for(Node* i = path.head->next; i != 0; i = i->next)
	{
		ss << ((Directory*)(i->addr))->getName() << "/";
	}
	ss << endl;
	return ss.str();
}


string Instruction::cat(vector<string> args)
{
	//环境检测
	checkEmpty();
	
	//参数检测
	if(args.size() < 2 || args.at(1) == "-r" &&  args.size() < 4)
	{
		return "cat format error: see \"cat [-r] filename\"\n";
	}
	
	Directory* top = (Directory*)(path.top());
	
	//如是是写文件
	if(args.at(1) == "-r")
	{
		File* file = top->getFile(args.at(2));
		
		//如果名字不合法
		if(!__can(args.at(2)))
		{
			return nameIllegal;
		}
		
		//文件如果存在，则删除之
		if(file != 0)
		{
			top->removeAFile(args.at(2));
		}
		
		//cout << "创始文件" << endl;
		//创始一个新的文件
		if(top->createAFile(args.at(2)))
		{
			file = top->getFile(args.at(2));
		}else
		{
			return "create file failed. Maybe the disk has been full.\n";	
		}
		
		
		//cout << "创始文件成功" << endl;
		//把分割的参数拼成字符串
		stringstream ss;
		for(int i = 3; i <args.size(); i++)
		{
			ss << args.at(i);
			if(i != args.size() - 1)
			{
				ss << " ";
			}
		}
		
		//把字符串写入文件当中
		string s = ss.str();
		int length = s.size() + 1;
		char* content = new char[length];
		strcpy(content, s.c_str());
		int ret = file->write(content, length);
		delete[] content;
		delete file;
		
		//如果写入成功
		if(ret == length)
		{
			return "write succeed\n";
		}else
		{
			return "write file failed. Maybe the disk has been full.\n";
		}
	
	//如果是读文件	
	}else
	{
		File* file = top->getFile(args.at(1));
		
		//如果文件不存在
		if(file == 0)
		{
			return "the filename '" + args.at(1) + "' is not exists\n";
		}
		
		int length = file->size();
		
		//如果是空文件
		if(length == 0)
		{
			delete file;
			return "";
		}
		
		//将文件内容全部读出
		char* content = new char[length];
		int act = file->read(content, length);
		content[length - 1] = 0;     //强制结束，防止出错
		string ret = string(content);
		delete[] content;
		delete file;
		return ret;
	}
}



string Instruction::df(vector<string> args)
{	//环境检测
	checkEmpty();
	
	//获得必要信息
	int total;
	int remain;
	if(getFileSystemInfo(this->disk, total, remain))
	{
		stringstream ss;
		ss << setw(10) << "FileSystem" << "\t";
		ss << setw(10) << "1-K block" << "\t";
		ss << setw(10) << "used" << "\t";
		ss << setw(10) << "remain" << "\t";
		ss << setw(10) << "percent" << endl;
		ss << setw(10) << "LightFS" << "\t";
		ss << setw(10) << total << "\t";
		ss << setw(10) << (total - remain) << "\t";
		ss << setw(10) << remain << "\t";
		ss << setw(10) << (remain * 100 / total) << "%" << endl;
		return ss.str();
	}
	return "未知的异常\n";
}

